#include <bits/stdc++.h>

#define pb push_back
#define eb emplace_back
#define fi first
#define se second
#define in read()
#define rep(i, x, y) for(int i = (x); i <= (y); i++)
#define per(i, x, y) for(int i = (x); i >= (y); i--)

using namespace std;

using ll = long long;
using db = double;
using pii = pair < int, int >;
using vec = vector < int >;
using veg = vector < pii >;

int read() {
	int x = 0; bool f = 0; char ch = getchar();
	while(!isdigit(ch)) f |= ch == '-', ch = getchar();
	while(isdigit(ch)) x = x * 10 + (ch ^ 48), ch = getchar();
	return f ? -x : x;
}

const int N = 1e5 + 10;

int dep[N], n, Q;
vec G[N], del[N];
int L[N], pot[N << 1], tot, fa[N];

namespace T {
	const int N = 2e5 + 10;
	const int K = 18;
	int R[N], f[K + 2][N], lg[N];
	inline int tmin(const int &x, const int &y) { return dep[x] < dep[y] ? x : y; } 
	void dfs(int x, int p) {
		pot[L[x] = R[x] = ++tot] = x; dep[x] = dep[p] + 1; fa[x] = p;
		for(auto y : G[x]) if(y ^ p) dfs(y, x), pot[R[x] = ++tot] = x;
	}
	void init() {
		dfs(1, 0); rep(i, 1, tot) f[0][i] = pot[i];
		rep(i, 1, K)
			rep(j, 1, tot)
			f[i][j] = tmin(f[i - 1][j], f[i - 1][j + (1 << (i - 1))]);
		rep(i, 2, tot) lg[i] = lg[i >> 1] + 1;
	}
	int lca(int x, int y) { if(x == 0 || y == 0) return 0; if(L[x] > L[y]) swap(x, y); x = L[x]; y = R[y]; int k = lg[y - x + 1]; return tmin(f[k][x], f[k][y - (1 << k) + 1]); }
	int dis(int x, int y) { return x == 0 || y == 0 ? 0 : dep[x] + dep[y] - 2 * dep[lca(x, y)]; }
}

int rt[N];

namespace seg {
	const int N = 1e7 + 10;
	int tot[N], lp[N], rp[N], c[N];
	int ch[N][2], rt, ndn;
	vec tpot;
	int nd() {
		int x; if(tpot.size()) x = tpot.back(), tpot.pop_back();
		else x = ++ndn;
		ch[x][0] = ch[x][1] = tot[x] = lp[x] = rp[x] = c[x] = 0;
		return x;
	}
	void pu(int o) {
		tot[o] = tot[ch[o][0]] + tot[ch[o][1]] - dep[T :: lca(rp[ch[o][0]], lp[ch[o][1]])];
		lp[o] = lp[ch[o][0]] ? lp[ch[o][0]] : lp[ch[o][1]];
		rp[o] = rp[ch[o][1]] ? rp[ch[o][1]] : rp[ch[o][0]];
		c[o] = min(c[ch[o][0]], c[ch[o][1]]);
	}
	void set(int o, int l, int v) {	c[o] = v; if(v > 0) lp[o] = l, rp[o] = l, tot[o] = dep[l]; else lp[o] = rp[o] = tot[o] = 0; }
	void upd(int &o, int pos, int v, int l = 1, int r = ::tot) {
		if(!o) o = nd(); if(l == r) return set(o, pot[l], c[o] += v); int mid = l + r >> 1;
		if(L[pos] <= mid) upd(ch[o][0], pos, v, l, mid); else upd(ch[o][1], pos, v, mid + 1, r);
		pu(o);
	}
	int merge(int x, int y, int l, int r) {
		if(!x || !y) return x | y;
		if(l == r) { c[x] += c[y]; set(x, pot[l], c[x]); tpot.eb(y); return x; }
		int mid = l + r >> 1;
		ch[x][0] = merge(ch[x][0], ch[y][0], l, mid); ch[x][1] = merge(ch[x][1], ch[y][1], mid + 1, r);
		tpot.eb(y); pu(x); return x;
	}
	int query(int x) { return tot[x] - dep[T :: lca(lp[x], rp[x])]; }
}

ll ans;

void dfs(int x, int p) {
	for(auto y : G[x]) if(p ^ y) dfs(y, x), rt[x] = seg :: merge(rt[x], rt[y], 1, tot);
	for(auto y : del[x]) seg :: upd(rt[x], y, -1);
	ans += seg :: query(rt[x]);
}

int main() {
#ifndef ONLINE_JUDGE
	freopen("1.in", "r", stdin);
#endif
	n = in, Q = in; rep(i, 2, n) { int u = in, v = in; G[u].eb(v); G[v].eb(u); }
	T :: init();
	while(Q--) {
		int s = in, t = in, L = T :: lca(s, t);
		seg :: upd(rt[s], s, 1); seg :: upd(rt[s], t, 1);
		seg :: upd(rt[t], s, 1); seg :: upd(rt[t], t, 1);
		//seg :: upd(rt[L], s, -1); seg :: upd(rt[L], t, -1);
		//seg :: upd(rt[fa[L]], s, -1); seg :: upd(rt[fa[L]], t, -1);
		del[L].eb(s); del[L].eb(t); del[fa[L]].eb(s); del[fa[L]].eb(t); 
	}
	dfs(1, 0); printf("%lld\n", ans / 2);
	return 0;
}
